<!DOCTYPE html>
            
<HTML>
<HEAD>
<meta name="booktitle" content="Developing Applications With Objective Caml" >
 <meta charset="ISO-8859-1"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<META name="GENERATOR" content="hevea 1.05-7 of 2000-02-24">
<META NAME="Author" CONTENT="Christian.Queinnec@lip6.fr">
<LINK rel=stylesheet type="text/css" href="videoc-ocda.css">
<script language="JavaScript" src="videoc.js"><!--
//--></script>
<TITLE>
 Modules as Compilation Units
</TITLE>
</HEAD>
<BODY class="regularBody">
<A HREF="book-ora129.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora131.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
<HR>

<H2> Modules as Compilation Units</H2>
The Objective CAML distribution includes a number of predefined modules.
We saw in chapter&nbsp;<A HREF="index.html#chap-Bibliotheques">8</A> how to use these modules in
a program. Here, we will show how users can define similar modules.<BR>
<BR>
<A NAME="toc180"></A>
<H3> Interface and Implementation</H3>
<A NAME="@fonctions370"></A>The module <TT>Stack</TT> from the distribution provides the main
functions on stacks, that is, queues with ``last in, first out''
discipline.


<PRE><BR># <B>let</B><CODE> </CODE>queue<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Stack.create<CODE> </CODE>()<CODE> </CODE>;;<BR><CODE>val queue : '_a Stack.t = &lt;abstr&gt;</CODE><BR># Stack.push<CODE> </CODE><CODE>1</CODE><CODE> </CODE>queue<CODE> </CODE>;<CODE> </CODE>Stack.push<CODE> </CODE><CODE>2</CODE><CODE> </CODE>queue<CODE> </CODE>;<CODE> </CODE>Stack.push<CODE> </CODE><CODE>3</CODE><CODE> </CODE>queue<CODE> </CODE>;;<BR><CODE>- : unit = ()</CODE><BR># Stack.iter<CODE> </CODE><TT>(</TT><B>fun</B><CODE> </CODE>n<CODE> </CODE>-&gt;<CODE> </CODE>Printf.printf<CODE> </CODE><CODE>"%d "</CODE><CODE> </CODE>n<TT>)</TT><CODE> </CODE><CODE> </CODE>queue<CODE> </CODE>;;<BR><CODE>3 2 1 - : unit = ()</CODE><BR>

</PRE>
<BR>
<BR>
Since Objective CAML is distributed with full source code, we can look at
the actual implementation of stacks.<BR>
<BR>
 <TT>ocaml-2.04/stdlib/stack.ml</TT><TT><BR></TT><B>type</B><CODE> </CODE><I>'a</I><CODE> </CODE>t<CODE> </CODE><CODE>=</CODE><CODE> </CODE>{<CODE> </CODE><B>mutable</B><CODE> </CODE>c<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>list<CODE> </CODE>}<BR><B>exception</B><CODE> </CODE>Empty<BR><B>let</B><CODE> </CODE>create<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>{<CODE> </CODE>c<CODE> </CODE><CODE>=</CODE><CODE> </CODE>[]<CODE> </CODE>}<BR><B>let</B><CODE> </CODE>clear<CODE> </CODE>s<CODE> </CODE><CODE>=</CODE><CODE> </CODE>s<CODE>.</CODE>c<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>[]<BR><B>let</B><CODE> </CODE>push<CODE> </CODE>x<CODE> </CODE>s<CODE> </CODE><CODE>=</CODE><CODE> </CODE>s<CODE>.</CODE>c<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>x<CODE> </CODE>::<CODE> </CODE>s<CODE>.</CODE>c<BR><B>let</B><CODE> </CODE>pop<CODE> </CODE>s<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>match</B><CODE> </CODE>s<CODE>.</CODE>c<CODE> </CODE><B>with</B><CODE> </CODE><CODE> </CODE>hd::tl<CODE> </CODE>-&gt;<CODE> </CODE>s<CODE>.</CODE>c<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>tl;<CODE> </CODE>hd<CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE> </CODE>[]<CODE> </CODE><CODE> </CODE>-&gt;<CODE> </CODE>raise<CODE> </CODE>Empty<BR><B>let</B><CODE> </CODE>length<CODE> </CODE>s<CODE> </CODE><CODE>=</CODE><CODE> </CODE>List.length<CODE> </CODE>s<CODE>.</CODE>c<BR><B>let</B><CODE> </CODE>iter<CODE> </CODE>f<CODE> </CODE>s<CODE> </CODE><CODE>=</CODE><CODE> </CODE>List.iter<CODE> </CODE>f<CODE> </CODE>s<CODE>.</CODE>c<BR><BR>
<BR>
We see that the type of stacks (written <TT>Stack.t</TT> outside the
<TT>Stack</TT> module and just <TT>t</TT> inside) is a record with one
mutable field containing a list. The list holds the contents of the
stack, with the list head corresponding to the stack top. Stack
operations are implemented as the basic list operations applied to the
field of the record.<BR>
<BR>
Armed with this insider's knowledge, we could try to access directly
the list representing a stack. However, Objective CAML will not let us do this.


<PRE><BR># <B>let</B><CODE> </CODE>list<CODE> </CODE><CODE>=</CODE><CODE> </CODE>queue<CODE>.</CODE>c<CODE> </CODE>;;<BR><CODE>Characters 12-19:</CODE><BR><CODE>Unbound label c</CODE><BR>

</PRE>

The compiler complains as if it did not know that <TT>Stack.t</TT>
is a record type with a field <TT>c</TT>. It is actually the case, as
we can see by looking at the interface of the <TT>Stack</TT> module.<BR>
<BR>
 <TT>ocaml-2.04/stdlib/stack.mli</TT><TT><BR></TT><CODE>(* Module [Stack]: last-in first-out stacks *)</CODE><BR><CODE>(* This module implements stacks (LIFOs), with in-place modification. *)</CODE><BR><BR><B>type</B><CODE> </CODE><I>'a</I><CODE> </CODE>t<CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>(* The type of stacks containing elements of type ['a]. *)</CODE><BR><BR><B>exception</B><CODE> </CODE>Empty<CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>(* Raised when [pop] is applied to an empty stack. *)</CODE><BR><BR><B>val</B><CODE> </CODE>create<CODE>:</CODE><CODE> </CODE>unit<CODE> </CODE>-&gt;<CODE> </CODE><I>'a</I><CODE> </CODE>t<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>(* Return a new stack, initially empty. *)</CODE><BR><B>val</B><CODE> </CODE>push<CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>-&gt;<CODE> </CODE><I>'a</I><CODE> </CODE>t<CODE> </CODE>-&gt;<CODE> </CODE>unit<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>(* [push x s] adds the element [x] at the top of stack [s]. *)</CODE><BR><B>val</B><CODE> </CODE>pop<CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>t<CODE> </CODE>-&gt;<CODE> </CODE><I>'a</I><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>(* [pop s] removes and returns the topmost element in stack [s],</CODE><BR><CODE>           or raises [Empty] if the stack is empty. *)</CODE><BR><B>val</B><CODE> </CODE>clear<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>t<CODE> </CODE>-&gt;<CODE> </CODE>unit<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>(* Discard all elements from a stack. *)</CODE><BR><B>val</B><CODE> </CODE>length<CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>t<CODE> </CODE>-&gt;<CODE> </CODE>int<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>(* Return the number of elements in a stack. *)</CODE><BR><B>val</B><CODE> </CODE>iter<CODE>:</CODE><CODE> </CODE><TT>(</TT><I>'a</I><CODE> </CODE>-&gt;<CODE> </CODE>unit<TT>)</TT><CODE> </CODE>-&gt;<CODE> </CODE><I>'a</I><CODE> </CODE>t<CODE> </CODE>-&gt;<CODE> </CODE>unit<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>(* [iter f s] applies [f] in turn to all elements of [s],</CODE><BR><CODE>           from the element at the top of the stack to the element at the</CODE><BR><CODE>           bottom of the stack. The stack itself is unchanged. *)</CODE><BR><BR>
<BR>
<A NAME="@concepts280"></A>
<A NAME="@concepts281"></A>
<A NAME="@concepts282"></A>
In addition to comments documenting the functions of the module,
this file lists explicitly the value, type and exception identifiers
defined in the file <TT>stack.ml</TT> that should be visible to clients
of the <TT>Stack</TT> module. More precisely, the interface declares
the names and type specifications for these exported definitions.
In particular, the type name <TT>t</TT> is exported, but the
representation of this type (that is, as a record with one <TT>c</TT>
field) is not given in this interface. Thus, clients of the
<TT>Stack</TT> module do not know how the type <TT>Stack.t</TT> is
represented, and cannot access directly values of this type. We say
that the type <I>Stack.t</I> is <EM>abstract</EM>, or <EM>opaque</EM>.<BR>
<BR>
The interface also declares the functions operating on stacks, giving
their names and types. (The types must be provided explicitly so that
the type checker can check that these functions are correctly used.)
Declaration of values and functions in an interface is achieved via
the following construct:
<A NAME="@fonctions371"></A>


<H3> Syntax </H3> <HR>


<B>val</B> <I>nom</I> <B>:</B> <I>type</I> 



<HR>

<BR>
<BR>
<A NAME="toc181"></A>
<H3> Relating Interfaces and Implementations</H3>As shown above, the <TT>Stack</TT> is composed of two parts: an
implementation providing definitions, and an interface providing
declarations for those definitions that are exported.
All module components declared in the interface must have a matching
definition in the implementation. Also, the types of values and
functions as defined in the implementation must match the types
declared in the interface.<BR>
<BR>
The relationship between interface and implementation is not
symmetrical. The implementation can contain more definitions than
requested by the interface. Typically, the definition of an
exported function can use auxiliary functions whose names will not
appear in the interface. Such auxiliary functions cannot be called
directly by a client of the module. Similarly, the interface can
restrict the type of a definition. Consider a module defining the
function <TT>id</TT> as the identity function
(<B>let</B><CODE> </CODE>id<CODE> </CODE>x<CODE> </CODE><CODE>=</CODE><CODE> </CODE>x). Its interface can declare <TT>id</TT>
with the type <I>int  -&gt; nt</I> (instead of the more general
<I>'a  -&gt; a</I>). Then, clients of this module can only apply
<TT>id</TT> to integers.<BR>
<BR>
Since the interface of a module is clearly separated from its
implementation, it becomes possible to have several implementations
for the same interface, for instance to test different algorithms or
data structures for the same operations. As an example, here is an
alternate implementation for the <TT>Stack</TT> module, based on
arrays instead of lists.<BR>
<BR>


<PRE><BR><B>type</B><CODE> </CODE><I>'a</I><CODE> </CODE>t<CODE> </CODE><CODE>=</CODE><CODE> </CODE>{<CODE> </CODE><B>mutable</B><CODE> </CODE>sp<CODE> </CODE><CODE>:</CODE><CODE> </CODE>int;<CODE> </CODE><B>mutable</B><CODE> </CODE>c<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>array<CODE> </CODE>}<BR><B>exception</B><CODE> </CODE>Empty<BR><B>let</B><CODE> </CODE>create<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>{<CODE> </CODE>sp<CODE>=</CODE><CODE>0</CODE><CODE> </CODE>;<CODE> </CODE>c<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>[||]</CODE><CODE> </CODE>}<BR><B>let</B><CODE> </CODE>clear<CODE> </CODE>s<CODE> </CODE><CODE>=</CODE><CODE> </CODE>s<CODE>.</CODE>sp<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE><CODE>0</CODE>;<CODE> </CODE>s<CODE>.</CODE>c<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE><CODE>[||]</CODE><BR><B>let</B><CODE> </CODE>size<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>5</CODE><CODE> </CODE><BR><B>let</B><CODE> </CODE>increase<CODE> </CODE>s<CODE> </CODE><CODE>=</CODE><CODE> </CODE>s<CODE>.</CODE>c<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>Array.append<CODE> </CODE>s<CODE>.</CODE>c<CODE> </CODE><TT>(</TT>Array.create<CODE> </CODE>size<CODE> </CODE>s<CODE>.</CODE>c<CODE>.</CODE><TT>(</TT><CODE>0</CODE><TT>)</TT><TT>)</TT><BR><BR><B>let</B><CODE> </CODE>push<CODE> </CODE>x<CODE> </CODE>s<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><B>if</B><CODE> </CODE>s<CODE>.</CODE>sp<CODE> </CODE><CODE>&gt;=</CODE><CODE> </CODE>Array.length<CODE> </CODE>s<CODE>.</CODE>c<CODE> </CODE><B>then</B><CODE> </CODE>increase<CODE> </CODE>s<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE>s<CODE>.</CODE>c<CODE>.</CODE><TT>(</TT>s<CODE>.</CODE>sp<TT>)</TT><CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>x<CODE> </CODE>;<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE>s<CODE>.</CODE>sp<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>succ<CODE> </CODE>s<CODE>.</CODE>sp<BR><BR><B>let</B><CODE> </CODE>pop<CODE> </CODE>s<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><B>if</B><CODE> </CODE>s<CODE>.</CODE>sp<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>0</CODE><CODE> </CODE><B>then</B><CODE> </CODE>raise<CODE> </CODE>Empty<BR><CODE> </CODE><CODE> </CODE><B>else</B><CODE> </CODE><B>let</B><CODE> </CODE>x<CODE> </CODE><CODE>=</CODE><CODE> </CODE>s<CODE>.</CODE>c<CODE>.</CODE><TT>(</TT>s<CODE>.</CODE>sp<TT>)</TT><CODE> </CODE><B>in</B><CODE> </CODE>s<CODE>.</CODE>sp<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>pred<CODE> </CODE>s<CODE>.</CODE>sp<CODE> </CODE>;<CODE> </CODE>x<BR><BR><B>let</B><CODE> </CODE>length<CODE> </CODE>s<CODE> </CODE><CODE>=</CODE><CODE> </CODE>s<CODE>.</CODE>sp<BR><B>let</B><CODE> </CODE>iter<CODE> </CODE>f<CODE> </CODE>s<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>for</B><CODE> </CODE>i<CODE> </CODE><CODE>=</CODE><CODE> </CODE>pred<CODE> </CODE>s<CODE>.</CODE>sp<CODE> </CODE><B>downto</B><CODE> </CODE><CODE>0</CODE><CODE> </CODE><B>do</B><CODE> </CODE>f<CODE> </CODE>s<CODE>.</CODE>sc<CODE>.</CODE><TT>(</TT>i<TT>)</TT><CODE> </CODE><B>done</B><BR>

</PRE>
<BR>
<BR>
This new implementation satisfies the requisites of the interface file
<CODE>stack.mli</CODE>. Thus, it can be used instead of the predefined
implementation of <TT>Stack</TT> in any program.<BR>
<BR>
<A NAME="toc182"></A>
<H3> Separate Compilation</H3><A NAME="@fonctions372"></A>
Like most modern programming languages, Objective CAML supports the
decomposition of programs into multiple compilation units, separately
compiled. A compilation unit is composed of two files, an
implementation file (with extension <TT>.ml</TT>) and an interface file
(with extension <TT>.mli</TT>). Each compilation unit is viewed as a
module. Compiling the implementation file <TT>name.ml</TT> defines the
module named <TT>Name</TT><A NAME="text36" HREF="book-ora137.html#note36"><SUP><FONT SIZE=2>1</FONT></SUP></A>.<BR>
<BR>
Values, types and exceptions defined in a module can be referenced
either via the <EM>dot notation</EM>
(<TT>Module</TT>.<TT>identifier</TT>), also known as <EM>qualified
identifiers</EM>, or via the <B>open</B> construct.<BR>
<BR>
<DIV ALIGN=center>
<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=1>
<TR><TD  ALIGN=left NOWRAP>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <TT>a.ml</TT></TD>
<TD  ALIGN=left NOWRAP>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <TT>b.ml</TT></TD>
</TR>
<TR><TD  ALIGN=left NOWRAP><B>type</B><CODE> </CODE>t<CODE> </CODE><CODE>=</CODE><CODE> </CODE>{<CODE> </CODE>x<CODE>:</CODE>int<CODE> </CODE>;<CODE> </CODE>y<CODE>:</CODE>int<CODE> </CODE>}<CODE> </CODE>;;</TD>
<TD  ALIGN=left NOWRAP><B>let</B><CODE> </CODE><B>val</B><CODE> </CODE><CODE>=</CODE><CODE> </CODE>{<CODE> </CODE>A.x<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>1</CODE><CODE> </CODE>;<CODE> </CODE>A.y<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>2</CODE><CODE> </CODE>}<CODE> </CODE>;;</TD>
</TR>
<TR><TD  ALIGN=left NOWRAP><B>let</B><CODE> </CODE>f<CODE> </CODE>c<CODE> </CODE><CODE>=</CODE><CODE> </CODE>c<CODE>.</CODE>x<CODE> </CODE><CODE>+</CODE><CODE> </CODE>c<CODE>.</CODE>y<CODE> </CODE>;;</TD>
<TD  ALIGN=left NOWRAP>A.f<CODE> </CODE><B>val</B><CODE> </CODE>;;</TD>
</TR>
<TR><TD  ALIGN=left NOWRAP>&nbsp;</TD>
<TD  ALIGN=left NOWRAP><B>open</B><CODE> </CODE>A<CODE> </CODE>;;</TD>
</TR>
<TR><TD  ALIGN=left NOWRAP>&nbsp;</TD>
<TD  ALIGN=left NOWRAP>f<CODE> </CODE><B>val</B><CODE> </CODE>;;</TD>
</TR></TABLE>
</DIV><BR>
An interface file (<TT>.mli</TT> file) must be compiled using the
<CODE>ocamlc -c</CODE> command before any module that depends on this
interface is compiled; this includes both clients of the module and
the implementation file for this module as well.<BR>
<BR>
If no interface file is provided for an implementation file, Objective CAML
considers that the module exports everything; that is, all identifiers
defined in the implementation file are present in the implicit
interface with their most general types.<BR>
<BR>
The linking phase to produce an executable file is performed as
described in chapter&nbsp;<A HREF="index.html#chap-Compilation">7</A>: the
<TT>ocamlc</TT> command (without the <TT>-c</TT> option), followed by the
object files for all compilation units comprising the program.
Warning: object files must be provided on the command line in
dependency order. That is, if a module <TT>B</TT> references another
module <TT>A</TT>, the object file <TT>a.cmo</TT> must precede <TT>b.cmo</TT>
on the linker command line. Consequently, cross dependencies between
two modules are forbidden.<BR>
<BR>
For instance, to generate an executable file from the source files
<TT>a.ml</TT> and <TT>b.ml</TT>, with matching interface files <TT>a.mli</TT>
and <TT>b.mli</TT>, we issue the following commands:
<PRE>
&gt; ocamlc -c a.mli
&gt; ocamlc -c a.ml
&gt; ocamlc -c b.mli
&gt; ocamlc -c b.ml
&gt; ocamlc a.cmo b.cmo
</PRE>Compilation units, composed of one interface file and one
implementation file, support separate compilation and information
hiding. However, their abilities as a general program structuring
tool are low. In particular, there is a one-to-one connection
between modules and files, preventing a program to use simultaneously
several implementations of a given interface, or also several
interfaces for the same implementation. Nested modules and module
parameterization are not supported either. To palliate those weaknesses, 
Objective CAML offers a module language, with special syntax and linguistic
constructs, to manipulate modules inside the language itself. The
remainder of this chapter introduces this module language.<BR>
<BR>
<HR>
<A HREF="book-ora129.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora131.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
</BODY>
</HTML>
